#include <assert.h>
#include <iostream>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include<sys/wait.h>
using namespace std;

void handler(int sig)
{
    cout << "I am father process get message: " << sig << endl;

    while (1)
    {
        pid_t rid = waitpid(-1,nullptr,WNOHANG);

        if(rid>0)
        {
            cout << "wait success "  << endl;
        }
        else
        {
            break;
        }
    }
    
}
int main()
{

    signal(17, handler);

    for (int i = 0; i < 100; i++)//第一个问题：创建100个线程，父进程该怎么回收呢？
    {

        pid_t id = fork();

        if (0 == id)
        {
            int cnt = 5;
            while (cnt)
            {
                cout << "I am child process pid: " << getpid() << endl;
                cnt--;
                sleep(1);
            }
            exit(0);
        }
    }
    while (1)
        ;
    cout << "quit normal" << getpid() << endl;
    return 0;
}

// volatile int g_flag = 0;
// // int g_flag = 0;

// void changeflag(int signo)
// {
//     (void)signo;
//     printf("将g_flag,从%d->%d\n", g_flag, 1);
//     g_flag = 1;
// }

// int main()
// {
//     signal(2, changeflag);

//     while (!g_flag)
//         ; // 故意写成这个样子, 编译器默认会对我们的代码进行自动优化！
//     // {
//     //     printf("hello world\n");
//     //     sleep(1);
//     // }

//     printf("process quit normal\n");
//     return 0;
// }

// void PrintSig(sigset_t pending)
// {
//     cout << "pending bitmap: ";

//     for (int i = 31; i > 0; i--)
//     {
//         if (sigismember(&pending, i))
//             cout << "1";
//         else
//             cout << "0";
//     }
//     cout << endl;
//     sleep(1);
// }

// void handler(int signo)
// {
//     cout << "get signo: " << signo << endl;
//     sigset_t pending;
//     sigemptyset(&pending);
//     while (true)
//     {

//         int n3 = sigpending(&pending);
//         assert(n3 == 0);

//         PrintSig(pending);
//     }
// }

// int main()
// {
//     struct sigaction act, oact;
//     act.sa_handler = handler;
//     act.sa_flags = 0;
//     // for(int signo = 1; signo <= 31; signo++) // 9， 19号信号无法被屏蔽， 18号信号会被做特殊处理
//     //     sigaddset(&block, signo); // SIGINT --- 根本就没有设置进当前进程的PCB block位图中
//     sigemptyset(&act.sa_mask);
//     sigaddset(&act.sa_mask, 3);
//     sigaddset(&act.sa_mask, 4);
//     sigaddset(&act.sa_mask, 5);

//     int n = sigaction(2, &act, &oact);
//     assert(n == 0);

//     cout << "I am a process! pid: " << getpid() << endl;
//     while (true)
//         sleep(1);

//     return 0;
// }

// void print(sigset_t pending)
// {
//     for (int num = 31; num > 0; num--)
//     {
//         if (sigismember(&pending, num))
//         {
//             cout << "1";
//         }
//         else
//         {
//             cout << "0";
//         }
//     }
//     cout << endl;
// }

// void handler(int sig)
// {
//     sigset_t set;
//     sigisemptyset(&set);
//     sigfillset(&set);

//     int n = sigpending(&set); // 我正在处理2号信号哦！！
//     // 将二号信号再次设置进入pending标准，模拟一直受到二号信号
//     assert(n == 0);

//     // 3. 打印pending位图中的收到的信号
//     std::cout << "递达中...: ";
//     print(set); //  递达之前，pending 2号已经被清0  先清零，再递达
//     std::cout << sig << " 号信号被递达处理..." << std::endl;
// }

// int main()
// {
//     // 屏蔽2号信号
//     signal(2, handler);

//     // 初始化sigset_t
//     // 定义一个sigset_t，并将其初始化，因为sigset_t是一个封装的结构体，我们也需要用封装的方法对其进行初始化
//     // 其实他并没有被设定进入blick表中
//     sigset_t ss, old_ss;
//     sigisemptyset(&ss);
//     sigfillset(&ss);
//     sigaddset(&ss, 2);//添加2号信号

//     // 此时才是调用系统调用接口，将信号集写入内核
//     //将屏蔽二号信号的block表写入内核
//     int n = sigprocmask(SIG_BLOCK, &ss, &old_ss);
//     assert(!n);

//     cout << "signal 2 getin block" << endl;
//     cout << "pid : " << getpid() << endl;

//     int cnt = 0;
//     while (true)
//     {
//         //获取当前的pending表
//         sigset_t pend;
//         sigisemptyset(&pend);
//         sigpending(&pend);

//         // 3. 打印pending位图中的收到的信号
//         print(pend);
//         cnt++;

//         // 4. 解除对2号信号的屏蔽
//         if (cnt == 20)
//         {
//             std::cout << "解除对2号信号的屏蔽" << std::endl;
//             n = sigprocmask(SIG_UNBLOCK, &ss, &old_ss); // 2号信号会被立即递达, 默认处理是终止进程
//             assert(n == 0);
//         }
//         // 我还想看到pending 2号信号 1->0 : 递达二号信号！
//         sleep(1);
//     }
// }

// int main()
// {
//     cout<<"pid :  "<<getpid()<<endl;
//     int cnt = 10;
//     while (cnt)
//     {
//         cnt--;
//     }

//     int a = 10;
//     cnt = a / 0;

//     return 0;
// }
